1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2012, Nexenta Systems, Inc. All rights reserved.
  24  */
  25 
  26 /*
  27  * Data-Link Driver
  28  */
  29 #include <sys/sysmacros.h>
  30 #include <sys/strsubr.h>
  31 #include <sys/strsun.h>
  32 #include <sys/vlan.h>
  33 #include <sys/dld_impl.h>
  34 #include <sys/mac_client.h>
  35 #include <sys/mac_client_impl.h>
  36 #include <sys/mac_client_priv.h>
  37 
  38 typedef void proto_reqfunc_t(dld_str_t *, mblk_t *);
  39 
  40 static proto_reqfunc_t proto_info_req, proto_attach_req, proto_detach_req,
  41     proto_bind_req, proto_unbind_req, proto_promiscon_req, proto_promiscoff_req,
  42     proto_enabmulti_req, proto_disabmulti_req, proto_physaddr_req,
  43     proto_setphysaddr_req, proto_udqos_req, proto_req, proto_capability_req,
  44     proto_notify_req, proto_passive_req, proto_exclusive_req;
  45 
  46 static void proto_capability_advertise(dld_str_t *, mblk_t *);
  47 static int dld_capab_poll_disable(dld_str_t *, dld_capab_poll_t *);
  48 static boolean_t check_mod_above(queue_t *, const char *);
  49 
  50 #define DL_ACK_PENDING(state) \
  51         ((state) == DL_ATTACH_PENDING || \
  52         (state) == DL_DETACH_PENDING || \
  53         (state) == DL_BIND_PENDING || \
  54         (state) == DL_UNBIND_PENDING)
  55 
  56 /*
  57  * Process a DLPI protocol message.
  58  * The primitives DL_BIND_REQ, DL_ENABMULTI_REQ, DL_PROMISCON_REQ,
  59  * DL_SET_PHYS_ADDR_REQ put the data link below our dld_str_t into an
  60  * 'active' state. The primitive DL_PASSIVE_REQ marks our dld_str_t
  61  * as 'passive' and forbids it from being subsequently made 'active'
  62  * by the above primitives.
  63  */
  64 void
  65 dld_proto(dld_str_t *dsp, mblk_t *mp)
  66 {
  67         t_uscalar_t             prim;
  68 
  69         if (MBLKL(mp) < sizeof (t_uscalar_t)) {
  70                 freemsg(mp);
  71                 return;
  72         }
  73         prim = ((union DL_primitives *)mp->b_rptr)->dl_primitive;
  74 
  75         switch (prim) {
  76         case DL_INFO_REQ:
  77                 proto_info_req(dsp, mp);
  78                 break;
  79         case DL_BIND_REQ:
  80                 proto_bind_req(dsp, mp);
  81                 break;
  82         case DL_UNBIND_REQ:
  83                 proto_unbind_req(dsp, mp);
  84                 break;
  85         case DL_UNITDATA_REQ:
  86                 proto_unitdata_req(dsp, mp);
  87                 break;
  88         case DL_UDQOS_REQ:
  89                 proto_udqos_req(dsp, mp);
  90                 break;
  91         case DL_ATTACH_REQ:
  92                 proto_attach_req(dsp, mp);
  93                 break;
  94         case DL_DETACH_REQ:
  95                 proto_detach_req(dsp, mp);
  96                 break;
  97         case DL_ENABMULTI_REQ:
  98                 proto_enabmulti_req(dsp, mp);
  99                 break;
 100         case DL_DISABMULTI_REQ:
 101                 proto_disabmulti_req(dsp, mp);
 102                 break;
 103         case DL_PROMISCON_REQ:
 104                 proto_promiscon_req(dsp, mp);
 105                 break;
 106         case DL_PROMISCOFF_REQ:
 107                 proto_promiscoff_req(dsp, mp);
 108                 break;
 109         case DL_PHYS_ADDR_REQ:
 110                 proto_physaddr_req(dsp, mp);
 111                 break;
 112         case DL_SET_PHYS_ADDR_REQ:
 113                 proto_setphysaddr_req(dsp, mp);
 114                 break;
 115         case DL_NOTIFY_REQ:
 116                 proto_notify_req(dsp, mp);
 117                 break;
 118         case DL_CAPABILITY_REQ:
 119                 proto_capability_req(dsp, mp);
 120                 break;
 121         case DL_PASSIVE_REQ:
 122                 proto_passive_req(dsp, mp);
 123                 break;
 124         case DL_EXCLUSIVE_REQ:
 125                 proto_exclusive_req(dsp, mp);
 126                 break;
 127         default:
 128                 proto_req(dsp, mp);
 129                 break;
 130         }
 131 }
 132 
 133 #define NEG(x)  -(x)
 134 typedef struct dl_info_ack_wrapper {
 135         dl_info_ack_t           dl_info;
 136         uint8_t                 dl_addr[MAXMACADDRLEN + sizeof (uint16_t)];
 137         uint8_t                 dl_brdcst_addr[MAXMACADDRLEN];
 138         dl_qos_cl_range1_t      dl_qos_range1;
 139         dl_qos_cl_sel1_t        dl_qos_sel1;
 140 } dl_info_ack_wrapper_t;
 141 
 142 /*
 143  * DL_INFO_REQ
 144  */
 145 static void
 146 proto_info_req(dld_str_t *dsp, mblk_t *mp)
 147 {
 148         dl_info_ack_wrapper_t   *dlwp;
 149         dl_info_ack_t           *dlp;
 150         dl_qos_cl_sel1_t        *selp;
 151         dl_qos_cl_range1_t      *rangep;
 152         uint8_t                 *addr;
 153         uint8_t                 *brdcst_addr;
 154         uint_t                  addr_length;
 155         uint_t                  sap_length;
 156         mac_info_t              minfo;
 157         mac_info_t              *minfop;
 158         queue_t                 *q = dsp->ds_wq;
 159 
 160         /*
 161          * Swap the request message for one large enough to contain the
 162          * wrapper structure defined above.
 163          */
 164         if ((mp = mexchange(q, mp, sizeof (dl_info_ack_wrapper_t),
 165             M_PCPROTO, 0)) == NULL)
 166                 return;
 167 
 168         bzero(mp->b_rptr, sizeof (dl_info_ack_wrapper_t));
 169         dlwp = (dl_info_ack_wrapper_t *)mp->b_rptr;
 170 
 171         dlp = &(dlwp->dl_info);
 172         ASSERT(dlp == (dl_info_ack_t *)mp->b_rptr);
 173 
 174         dlp->dl_primitive = DL_INFO_ACK;
 175 
 176         /*
 177          * Set up the sub-structure pointers.
 178          */
 179         addr = dlwp->dl_addr;
 180         brdcst_addr = dlwp->dl_brdcst_addr;
 181         rangep = &(dlwp->dl_qos_range1);
 182         selp = &(dlwp->dl_qos_sel1);
 183 
 184         /*
 185          * This driver supports only version 2 connectionless DLPI provider
 186          * nodes.
 187          */
 188         dlp->dl_service_mode = DL_CLDLS;
 189         dlp->dl_version = DL_VERSION_2;
 190 
 191         /*
 192          * Set the style of the provider
 193          */
 194         dlp->dl_provider_style = dsp->ds_style;
 195         ASSERT(dlp->dl_provider_style == DL_STYLE1 ||
 196             dlp->dl_provider_style == DL_STYLE2);
 197 
 198         /*
 199          * Set the current DLPI state.
 200          */
 201         dlp->dl_current_state = dsp->ds_dlstate;
 202 
 203         /*
 204          * Gratuitously set the media type. This is to deal with modules
 205          * that assume the media type is known prior to DL_ATTACH_REQ
 206          * being completed.
 207          */
 208         dlp->dl_mac_type = DL_ETHER;
 209 
 210         /*
 211          * If the stream is not at least attached we try to retrieve the
 212          * mac_info using mac_info_get()
 213          */
 214         if (dsp->ds_dlstate == DL_UNATTACHED ||
 215             dsp->ds_dlstate == DL_ATTACH_PENDING ||
 216             dsp->ds_dlstate == DL_DETACH_PENDING) {
 217                 if (!mac_info_get(ddi_major_to_name(dsp->ds_major), &minfo)) {
 218                         /*
 219                          * Cannot find mac_info. giving up.
 220                          */
 221                         goto done;
 222                 }
 223                 minfop = &minfo;
 224         } else {
 225                 minfop = (mac_info_t *)dsp->ds_mip;
 226                 /* We can only get the sdu if we're attached. */
 227                 mac_sdu_get(dsp->ds_mh, &dlp->dl_min_sdu, &dlp->dl_max_sdu);
 228         }
 229 
 230         /*
 231          * Set the media type (properly this time).
 232          */
 233         if (dsp->ds_native)
 234                 dlp->dl_mac_type = minfop->mi_nativemedia;
 235         else
 236                 dlp->dl_mac_type = minfop->mi_media;
 237 
 238         /*
 239          * Set the DLSAP length. We only support 16 bit values and they
 240          * appear after the MAC address portion of DLSAP addresses.
 241          */
 242         sap_length = sizeof (uint16_t);
 243         dlp->dl_sap_length = NEG(sap_length);
 244 
 245         addr_length = minfop->mi_addr_length;
 246 
 247         /*
 248          * Copy in the media broadcast address.
 249          */
 250         if (minfop->mi_brdcst_addr != NULL) {
 251                 dlp->dl_brdcst_addr_offset =
 252                     (uintptr_t)brdcst_addr - (uintptr_t)dlp;
 253                 bcopy(minfop->mi_brdcst_addr, brdcst_addr, addr_length);
 254                 dlp->dl_brdcst_addr_length = addr_length;
 255         }
 256 
 257         /* Only VLAN links and links that have a normal tag mode support QOS. */
 258         if ((dsp->ds_mch != NULL &&
 259             mac_client_vid(dsp->ds_mch) != VLAN_ID_NONE) ||
 260             (dsp->ds_dlp != NULL &&
 261             dsp->ds_dlp->dl_tagmode == LINK_TAGMODE_NORMAL)) {
 262                 dlp->dl_qos_range_offset = (uintptr_t)rangep - (uintptr_t)dlp;
 263                 dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t);
 264 
 265                 rangep->dl_qos_type = DL_QOS_CL_RANGE1;
 266                 rangep->dl_trans_delay.dl_target_value = DL_UNKNOWN;
 267                 rangep->dl_trans_delay.dl_accept_value = DL_UNKNOWN;
 268                 rangep->dl_protection.dl_min = DL_UNKNOWN;
 269                 rangep->dl_protection.dl_max = DL_UNKNOWN;
 270                 rangep->dl_residual_error = DL_UNKNOWN;
 271 
 272                 /*
 273                  * Specify the supported range of priorities.
 274                  */
 275                 rangep->dl_priority.dl_min = 0;
 276                 rangep->dl_priority.dl_max = (1 << VLAN_PRI_SIZE) - 1;
 277 
 278                 dlp->dl_qos_offset = (uintptr_t)selp - (uintptr_t)dlp;
 279                 dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t);
 280 
 281                 selp->dl_qos_type = DL_QOS_CL_SEL1;
 282                 selp->dl_trans_delay = DL_UNKNOWN;
 283                 selp->dl_protection = DL_UNKNOWN;
 284                 selp->dl_residual_error = DL_UNKNOWN;
 285 
 286                 /*
 287                  * Specify the current priority (which can be changed by
 288                  * the DL_UDQOS_REQ primitive).
 289                  */
 290                 selp->dl_priority = dsp->ds_pri;
 291         }
 292 
 293         dlp->dl_addr_length = addr_length + sizeof (uint16_t);
 294         if (dsp->ds_dlstate == DL_IDLE) {
 295                 /*
 296                  * The stream is bound. Therefore we can formulate a valid
 297                  * DLSAP address.
 298                  */
 299                 dlp->dl_addr_offset = (uintptr_t)addr - (uintptr_t)dlp;
 300                 if (addr_length > 0)
 301                         mac_unicast_primary_get(dsp->ds_mh, addr);
 302 
 303                 *(uint16_t *)(addr + addr_length) = dsp->ds_sap;
 304         }
 305 
 306 done:
 307         IMPLY(dlp->dl_qos_offset != 0, dlp->dl_qos_length != 0);
 308         IMPLY(dlp->dl_qos_range_offset != 0,
 309             dlp->dl_qos_range_length != 0);
 310         IMPLY(dlp->dl_addr_offset != 0, dlp->dl_addr_length != 0);
 311         IMPLY(dlp->dl_brdcst_addr_offset != 0,
 312             dlp->dl_brdcst_addr_length != 0);
 313 
 314         qreply(q, mp);
 315 }
 316 
 317 /*
 318  * DL_ATTACH_REQ
 319  */
 320 static void
 321 proto_attach_req(dld_str_t *dsp, mblk_t *mp)
 322 {
 323         dl_attach_req_t *dlp = (dl_attach_req_t *)mp->b_rptr;
 324         int             err = 0;
 325         t_uscalar_t     dl_err;
 326         queue_t         *q = dsp->ds_wq;
 327 
 328         if (MBLKL(mp) < sizeof (dl_attach_req_t) ||
 329             dlp->dl_ppa < 0 || dsp->ds_style == DL_STYLE1) {
 330                 dl_err = DL_BADPRIM;
 331                 goto failed;
 332         }
 333 
 334         if (dsp->ds_dlstate != DL_UNATTACHED) {
 335                 dl_err = DL_OUTSTATE;
 336                 goto failed;
 337         }
 338 
 339         dsp->ds_dlstate = DL_ATTACH_PENDING;
 340 
 341         err = dld_str_attach(dsp, dlp->dl_ppa);
 342         if (err != 0) {
 343                 switch (err) {
 344                 case ENOENT:
 345                         dl_err = DL_BADPPA;
 346                         err = 0;
 347                         break;
 348                 default:
 349                         dl_err = DL_SYSERR;
 350                         break;
 351                 }
 352                 dsp->ds_dlstate = DL_UNATTACHED;
 353                 goto failed;
 354         }
 355         ASSERT(dsp->ds_dlstate == DL_UNBOUND);
 356         dlokack(q, mp, DL_ATTACH_REQ);
 357         return;
 358 
 359 failed:
 360         dlerrorack(q, mp, DL_ATTACH_REQ, dl_err, (t_uscalar_t)err);
 361 }
 362 
 363 /*
 364  * DL_DETACH_REQ
 365  */
 366 static void
 367 proto_detach_req(dld_str_t *dsp, mblk_t *mp)
 368 {
 369         queue_t         *q = dsp->ds_wq;
 370         t_uscalar_t     dl_err;
 371 
 372         if (MBLKL(mp) < sizeof (dl_detach_req_t)) {
 373                 dl_err = DL_BADPRIM;
 374                 goto failed;
 375         }
 376 
 377         if (dsp->ds_dlstate != DL_UNBOUND) {
 378                 dl_err = DL_OUTSTATE;
 379                 goto failed;
 380         }
 381 
 382         if (dsp->ds_style == DL_STYLE1) {
 383                 dl_err = DL_BADPRIM;
 384                 goto failed;
 385         }
 386 
 387         ASSERT(dsp->ds_datathr_cnt == 0);
 388         dsp->ds_dlstate = DL_DETACH_PENDING;
 389 
 390         dld_str_detach(dsp);
 391         dlokack(dsp->ds_wq, mp, DL_DETACH_REQ);
 392         return;
 393 
 394 failed:
 395         dlerrorack(q, mp, DL_DETACH_REQ, dl_err, 0);
 396 }
 397 
 398 /*
 399  * DL_BIND_REQ
 400  */
 401 static void
 402 proto_bind_req(dld_str_t *dsp, mblk_t *mp)
 403 {
 404         dl_bind_req_t   *dlp = (dl_bind_req_t *)mp->b_rptr;
 405         int             err = 0;
 406         uint8_t         dlsap_addr[MAXMACADDRLEN + sizeof (uint16_t)];
 407         uint_t          dlsap_addr_length;
 408         t_uscalar_t     dl_err;
 409         t_scalar_t      sap;
 410         queue_t         *q = dsp->ds_wq;
 411         mac_perim_handle_t      mph;
 412         void            *mdip;
 413         int32_t         intr_cpu;
 414 
 415         if (MBLKL(mp) < sizeof (dl_bind_req_t)) {
 416                 dl_err = DL_BADPRIM;
 417                 goto failed;
 418         }
 419 
 420         if (dlp->dl_xidtest_flg != 0) {
 421                 dl_err = DL_NOAUTO;
 422                 goto failed;
 423         }
 424 
 425         if (dlp->dl_service_mode != DL_CLDLS) {
 426                 dl_err = DL_UNSUPPORTED;
 427                 goto failed;
 428         }
 429 
 430         if (dsp->ds_dlstate != DL_UNBOUND) {
 431                 dl_err = DL_OUTSTATE;
 432                 goto failed;
 433         }
 434 
 435         mac_perim_enter_by_mh(dsp->ds_mh, &mph);
 436 
 437         if ((err = dls_active_set(dsp)) != 0) {
 438                 dl_err = DL_SYSERR;
 439                 goto failed2;
 440         }
 441 
 442         dsp->ds_dlstate = DL_BIND_PENDING;
 443         /*
 444          * Set the receive callback.
 445          */
 446         dls_rx_set(dsp, (dsp->ds_mode == DLD_RAW) ?
 447             dld_str_rx_raw : dld_str_rx_unitdata, dsp);
 448 
 449         /*
 450          * Bind the channel such that it can receive packets.
 451          */
 452         sap = dlp->dl_sap;
 453         dsp->ds_nonip = !check_mod_above(dsp->ds_rq, "ip") &&
 454             !check_mod_above(dsp->ds_rq, "arp");
 455 
 456         err = dls_bind(dsp, sap);
 457         if (err != 0) {
 458                 switch (err) {
 459                 case EINVAL:
 460                         dl_err = DL_BADADDR;
 461                         err = 0;
 462                         break;
 463                 default:
 464                         dl_err = DL_SYSERR;
 465                         break;
 466                 }
 467 
 468                 dsp->ds_dlstate = DL_UNBOUND;
 469                 dls_active_clear(dsp, B_FALSE);
 470                 goto failed2;
 471         }
 472 
 473         intr_cpu = mac_client_intr_cpu(dsp->ds_mch);
 474         mdip = mac_get_devinfo(dsp->ds_mh);
 475         mac_perim_exit(mph);
 476 
 477         /*
 478          * We do this after we get out of the perim to avoid deadlocks
 479          * etc. since part of mac_client_retarget_intr is to walk the
 480          * device tree in order to find and retarget the interrupts.
 481          */
 482         if (intr_cpu != -1)
 483                 mac_client_set_intr_cpu(mdip, dsp->ds_mch, intr_cpu);
 484 
 485         /*
 486          * Copy in MAC address.
 487          */
 488         dlsap_addr_length = dsp->ds_mip->mi_addr_length;
 489         mac_unicast_primary_get(dsp->ds_mh, dlsap_addr);
 490 
 491         /*
 492          * Copy in the SAP.
 493          */
 494         *(uint16_t *)(dlsap_addr + dlsap_addr_length) = sap;
 495         dlsap_addr_length += sizeof (uint16_t);
 496 
 497         dsp->ds_dlstate = DL_IDLE;
 498         dlbindack(q, mp, sap, dlsap_addr, dlsap_addr_length, 0, 0);
 499         return;
 500 
 501 failed2:
 502         mac_perim_exit(mph);
 503 failed:
 504         dlerrorack(q, mp, DL_BIND_REQ, dl_err, (t_uscalar_t)err);
 505 }
 506 
 507 /*
 508  * DL_UNBIND_REQ
 509  */
 510 static void
 511 proto_unbind_req(dld_str_t *dsp, mblk_t *mp)
 512 {
 513         queue_t         *q = dsp->ds_wq;
 514         t_uscalar_t     dl_err;
 515         mac_perim_handle_t      mph;
 516 
 517         if (MBLKL(mp) < sizeof (dl_unbind_req_t)) {
 518                 dl_err = DL_BADPRIM;
 519                 goto failed;
 520         }
 521 
 522         if (dsp->ds_dlstate != DL_IDLE) {
 523                 dl_err = DL_OUTSTATE;
 524                 goto failed;
 525         }
 526 
 527         mutex_enter(&dsp->ds_lock);
 528         while (dsp->ds_datathr_cnt != 0)
 529                 cv_wait(&dsp->ds_datathr_cv, &dsp->ds_lock);
 530 
 531         dsp->ds_dlstate = DL_UNBIND_PENDING;
 532         mutex_exit(&dsp->ds_lock);
 533 
 534         mac_perim_enter_by_mh(dsp->ds_mh, &mph);
 535         /*
 536          * Unbind the channel to stop packets being received.
 537          */
 538         dls_unbind(dsp);
 539 
 540         /*
 541          * Disable polling mode, if it is enabled.
 542          */
 543         (void) dld_capab_poll_disable(dsp, NULL);
 544 
 545         /*
 546          * Clear LSO flags.
 547          */
 548         dsp->ds_lso = B_FALSE;
 549         dsp->ds_lso_max = 0;
 550 
 551         /*
 552          * Clear the receive callback.
 553          */
 554         dls_rx_set(dsp, NULL, NULL);
 555         dsp->ds_direct = B_FALSE;
 556 
 557         /*
 558          * Set the mode back to the default (unitdata).
 559          */
 560         dsp->ds_mode = DLD_UNITDATA;
 561         dsp->ds_dlstate = DL_UNBOUND;
 562 
 563         dls_active_clear(dsp, B_FALSE);
 564         mac_perim_exit(mph);
 565         dlokack(dsp->ds_wq, mp, DL_UNBIND_REQ);
 566         return;
 567 failed:
 568         dlerrorack(q, mp, DL_UNBIND_REQ, dl_err, 0);
 569 }
 570 
 571 /*
 572  * DL_PROMISCON_REQ
 573  */
 574 static void
 575 proto_promiscon_req(dld_str_t *dsp, mblk_t *mp)
 576 {
 577         dl_promiscon_req_t *dlp = (dl_promiscon_req_t *)mp->b_rptr;
 578         int             err = 0;
 579         t_uscalar_t     dl_err;
 580         uint32_t        new_flags, promisc_saved;
 581         queue_t         *q = dsp->ds_wq;
 582         mac_perim_handle_t      mph;
 583 
 584         if (MBLKL(mp) < sizeof (dl_promiscon_req_t)) {
 585                 dl_err = DL_BADPRIM;
 586                 goto failed;
 587         }
 588 
 589         if (dsp->ds_dlstate == DL_UNATTACHED ||
 590             DL_ACK_PENDING(dsp->ds_dlstate)) {
 591                 dl_err = DL_OUTSTATE;
 592                 goto failed;
 593         }
 594 
 595         mac_perim_enter_by_mh(dsp->ds_mh, &mph);
 596 
 597         new_flags = promisc_saved = dsp->ds_promisc;
 598         switch (dlp->dl_level) {
 599         case DL_PROMISC_SAP:
 600                 new_flags |= DLS_PROMISC_SAP;
 601                 break;
 602 
 603         case DL_PROMISC_MULTI:
 604                 new_flags |= DLS_PROMISC_MULTI;
 605                 break;
 606 
 607         case DL_PROMISC_PHYS:
 608                 new_flags |= DLS_PROMISC_PHYS;
 609                 break;
 610 
 611         case DL_PROMISC_RX_ONLY:
 612                 new_flags |= DLS_PROMISC_RX_ONLY;
 613                 break;
 614 
 615         case DL_PROMISC_FIXUPS:
 616                 new_flags |= DLS_PROMISC_FIXUPS;
 617                 break;
 618 
 619         default:
 620                 dl_err = DL_NOTSUPPORTED;
 621                 goto failed2;
 622         }
 623 
 624         if ((promisc_saved == 0) && (err = dls_active_set(dsp)) != 0) {
 625                 ASSERT(dsp->ds_promisc == promisc_saved);
 626                 dl_err = DL_SYSERR;
 627                 goto failed2;
 628         }
 629 
 630         /*
 631          * Adjust channel promiscuity.
 632          */
 633         err = dls_promisc(dsp, new_flags);
 634 
 635         if (err != 0) {
 636                 dl_err = DL_SYSERR;
 637                 dsp->ds_promisc = promisc_saved;
 638                 if (promisc_saved == 0)
 639                         dls_active_clear(dsp, B_FALSE);
 640                 goto failed2;
 641         }
 642 
 643         mac_perim_exit(mph);
 644 
 645         dlokack(q, mp, DL_PROMISCON_REQ);
 646         return;
 647 
 648 failed2:
 649         mac_perim_exit(mph);
 650 failed:
 651         dlerrorack(q, mp, DL_PROMISCON_REQ, dl_err, (t_uscalar_t)err);
 652 }
 653 
 654 /*
 655  * DL_PROMISCOFF_REQ
 656  */
 657 static void
 658 proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
 659 {
 660         dl_promiscoff_req_t *dlp = (dl_promiscoff_req_t *)mp->b_rptr;
 661         int             err = 0;
 662         t_uscalar_t     dl_err;
 663         uint32_t        new_flags;
 664         queue_t         *q = dsp->ds_wq;
 665         mac_perim_handle_t      mph;
 666 
 667         if (MBLKL(mp) < sizeof (dl_promiscoff_req_t)) {
 668                 dl_err = DL_BADPRIM;
 669                 goto failed;
 670         }
 671 
 672         if (dsp->ds_dlstate == DL_UNATTACHED ||
 673             DL_ACK_PENDING(dsp->ds_dlstate)) {
 674                 dl_err = DL_OUTSTATE;
 675                 goto failed;
 676         }
 677 
 678         mac_perim_enter_by_mh(dsp->ds_mh, &mph);
 679 
 680         new_flags = dsp->ds_promisc;
 681         switch (dlp->dl_level) {
 682         case DL_PROMISC_SAP:
 683                 if (!(dsp->ds_promisc & DLS_PROMISC_SAP)) {
 684                         dl_err = DL_NOTENAB;
 685                         goto failed;
 686                 }
 687                 new_flags &= ~DLS_PROMISC_SAP;
 688                 break;
 689 
 690         case DL_PROMISC_MULTI:
 691                 if (!(dsp->ds_promisc & DLS_PROMISC_MULTI)) {
 692                         dl_err = DL_NOTENAB;
 693                         goto failed;
 694                 }
 695                 new_flags &= ~DLS_PROMISC_MULTI;
 696                 break;
 697 
 698         case DL_PROMISC_PHYS:
 699                 if (!(dsp->ds_promisc & DLS_PROMISC_PHYS)) {
 700                         dl_err = DL_NOTENAB;
 701                         goto failed;
 702                 }
 703                 new_flags &= ~DLS_PROMISC_PHYS;
 704                 break;
 705 
 706         case DL_PROMISC_RX_ONLY:
 707                 if (!(dsp->ds_promisc & DLS_PROMISC_RX_ONLY)) {
 708                         dl_err = DL_NOTENAB;
 709                         goto failed;
 710                 }
 711                 new_flags &= ~DLS_PROMISC_RX_ONLY;
 712                 break;
 713 
 714         case DL_PROMISC_FIXUPS:
 715                 if (!(dsp->ds_promisc & DLS_PROMISC_FIXUPS)) {
 716                         dl_err = DL_NOTENAB;
 717                         goto failed;
 718                 }
 719                 new_flags &= ~DLS_PROMISC_FIXUPS;
 720                 break;
 721 
 722         default:
 723                 dl_err = DL_NOTSUPPORTED;
 724                 mac_perim_exit(mph);
 725                 goto failed;
 726         }
 727 
 728         /*
 729          * Adjust channel promiscuity.
 730          */
 731         err = dls_promisc(dsp, new_flags);
 732 
 733         if (err != 0) {
 734                 mac_perim_exit(mph);
 735                 dl_err = DL_SYSERR;
 736                 goto failed;
 737         }
 738 
 739         ASSERT(dsp->ds_promisc == new_flags);
 740         if (dsp->ds_promisc == 0)
 741                 dls_active_clear(dsp, B_FALSE);
 742 
 743         mac_perim_exit(mph);
 744 
 745         dlokack(q, mp, DL_PROMISCOFF_REQ);
 746         return;
 747 failed:
 748         dlerrorack(q, mp, DL_PROMISCOFF_REQ, dl_err, (t_uscalar_t)err);
 749 }
 750 
 751 /*
 752  * DL_ENABMULTI_REQ
 753  */
 754 static void
 755 proto_enabmulti_req(dld_str_t *dsp, mblk_t *mp)
 756 {
 757         dl_enabmulti_req_t *dlp = (dl_enabmulti_req_t *)mp->b_rptr;
 758         int             err = 0;
 759         t_uscalar_t     dl_err;
 760         queue_t         *q = dsp->ds_wq;
 761         mac_perim_handle_t      mph;
 762 
 763         if (dsp->ds_dlstate == DL_UNATTACHED ||
 764             DL_ACK_PENDING(dsp->ds_dlstate)) {
 765                 dl_err = DL_OUTSTATE;
 766                 goto failed;
 767         }
 768 
 769         if (MBLKL(mp) < sizeof (dl_enabmulti_req_t) ||
 770             !MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) ||
 771             dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) {
 772                 dl_err = DL_BADPRIM;
 773                 goto failed;
 774         }
 775 
 776         mac_perim_enter_by_mh(dsp->ds_mh, &mph);
 777 
 778         if ((dsp->ds_dmap == NULL) && (err = dls_active_set(dsp)) != 0) {
 779                 dl_err = DL_SYSERR;
 780                 goto failed2;
 781         }
 782 
 783         err = dls_multicst_add(dsp, mp->b_rptr + dlp->dl_addr_offset);
 784         if (err != 0) {
 785                 switch (err) {
 786                 case EINVAL:
 787                         dl_err = DL_BADADDR;
 788                         err = 0;
 789                         break;
 790                 case ENOSPC:
 791                         dl_err = DL_TOOMANY;
 792                         err = 0;
 793                         break;
 794                 default:
 795                         dl_err = DL_SYSERR;
 796                         break;
 797                 }
 798                 if (dsp->ds_dmap == NULL)
 799                         dls_active_clear(dsp, B_FALSE);
 800                 goto failed2;
 801         }
 802 
 803         mac_perim_exit(mph);
 804 
 805         dlokack(q, mp, DL_ENABMULTI_REQ);
 806         return;
 807 
 808 failed2:
 809         mac_perim_exit(mph);
 810 failed:
 811         dlerrorack(q, mp, DL_ENABMULTI_REQ, dl_err, (t_uscalar_t)err);
 812 }
 813 
 814 /*
 815  * DL_DISABMULTI_REQ
 816  */
 817 static void
 818 proto_disabmulti_req(dld_str_t *dsp, mblk_t *mp)
 819 {
 820         dl_disabmulti_req_t *dlp = (dl_disabmulti_req_t *)mp->b_rptr;
 821         int             err = 0;
 822         t_uscalar_t     dl_err;
 823         queue_t         *q = dsp->ds_wq;
 824         mac_perim_handle_t      mph;
 825 
 826         if (dsp->ds_dlstate == DL_UNATTACHED ||
 827             DL_ACK_PENDING(dsp->ds_dlstate)) {
 828                 dl_err = DL_OUTSTATE;
 829                 goto failed;
 830         }
 831 
 832         if (MBLKL(mp) < sizeof (dl_disabmulti_req_t) ||
 833             !MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) ||
 834             dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) {
 835                 dl_err = DL_BADPRIM;
 836                 goto failed;
 837         }
 838 
 839         mac_perim_enter_by_mh(dsp->ds_mh, &mph);
 840         err = dls_multicst_remove(dsp, mp->b_rptr + dlp->dl_addr_offset);
 841         if ((err == 0) && (dsp->ds_dmap == NULL))
 842                 dls_active_clear(dsp, B_FALSE);
 843         mac_perim_exit(mph);
 844 
 845         if (err != 0) {
 846         switch (err) {
 847                 case EINVAL:
 848                         dl_err = DL_BADADDR;
 849                         err = 0;
 850                         break;
 851 
 852                 case ENOENT:
 853                         dl_err = DL_NOTENAB;
 854                         err = 0;
 855                         break;
 856 
 857                 default:
 858                         dl_err = DL_SYSERR;
 859                         break;
 860                 }
 861                 goto failed;
 862         }
 863         dlokack(q, mp, DL_DISABMULTI_REQ);
 864         return;
 865 failed:
 866         dlerrorack(q, mp, DL_DISABMULTI_REQ, dl_err, (t_uscalar_t)err);
 867 }
 868 
 869 /*
 870  * DL_PHYS_ADDR_REQ
 871  */
 872 static void
 873 proto_physaddr_req(dld_str_t *dsp, mblk_t *mp)
 874 {
 875         dl_phys_addr_req_t *dlp = (dl_phys_addr_req_t *)mp->b_rptr;
 876         queue_t         *q = dsp->ds_wq;
 877         t_uscalar_t     dl_err = 0;
 878         char            *addr = NULL;
 879         uint_t          addr_length;
 880 
 881         if (MBLKL(mp) < sizeof (dl_phys_addr_req_t)) {
 882                 dl_err = DL_BADPRIM;
 883                 goto done;
 884         }
 885 
 886         if (dsp->ds_dlstate == DL_UNATTACHED ||
 887             DL_ACK_PENDING(dsp->ds_dlstate)) {
 888                 dl_err = DL_OUTSTATE;
 889                 goto done;
 890         }
 891 
 892         addr_length = dsp->ds_mip->mi_addr_length;
 893         if (addr_length > 0) {
 894                 addr = kmem_alloc(addr_length, KM_SLEEP);
 895                 switch (dlp->dl_addr_type) {
 896                 case DL_CURR_PHYS_ADDR:
 897                         mac_unicast_primary_get(dsp->ds_mh, (uint8_t *)addr);
 898                         break;
 899                 case DL_FACT_PHYS_ADDR:
 900                         bcopy(dsp->ds_mip->mi_unicst_addr, addr, addr_length);
 901                         break;
 902                 case DL_CURR_DEST_ADDR:
 903                         if (!mac_dst_get(dsp->ds_mh, (uint8_t *)addr))
 904                                 dl_err = DL_NOTSUPPORTED;
 905                         break;
 906                 default:
 907                         dl_err = DL_UNSUPPORTED;
 908                 }
 909         }
 910 done:
 911         if (dl_err == 0)
 912                 dlphysaddrack(q, mp, addr, (t_uscalar_t)addr_length);
 913         else
 914                 dlerrorack(q, mp, DL_PHYS_ADDR_REQ, dl_err, 0);
 915         if (addr != NULL)
 916                 kmem_free(addr, addr_length);
 917 }
 918 
 919 /*
 920  * DL_SET_PHYS_ADDR_REQ
 921  */
 922 static void
 923 proto_setphysaddr_req(dld_str_t *dsp, mblk_t *mp)
 924 {
 925         dl_set_phys_addr_req_t *dlp = (dl_set_phys_addr_req_t *)mp->b_rptr;
 926         int             err = 0;
 927         t_uscalar_t     dl_err;
 928         queue_t         *q = dsp->ds_wq;
 929         mac_perim_handle_t      mph;
 930 
 931         if (dsp->ds_dlstate == DL_UNATTACHED ||
 932             DL_ACK_PENDING(dsp->ds_dlstate)) {
 933                 dl_err = DL_OUTSTATE;
 934                 goto failed;
 935         }
 936 
 937         if (MBLKL(mp) < sizeof (dl_set_phys_addr_req_t) ||
 938             !MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) ||
 939             dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) {
 940                 dl_err = DL_BADPRIM;
 941                 goto failed;
 942         }
 943 
 944         mac_perim_enter_by_mh(dsp->ds_mh, &mph);
 945 
 946         if ((err = dls_active_set(dsp)) != 0) {
 947                 dl_err = DL_SYSERR;
 948                 goto failed2;
 949         }
 950 
 951         /*
 952          * If mac-nospoof is enabled and the link is owned by a
 953          * non-global zone, changing the mac address is not allowed.
 954          */
 955         if (dsp->ds_dlp->dl_zid != GLOBAL_ZONEID &&
 956             mac_protect_enabled(dsp->ds_mch, MPT_MACNOSPOOF)) {
 957                 dls_active_clear(dsp, B_FALSE);
 958                 err = EACCES;
 959                 goto failed2;
 960         }
 961 
 962         err = mac_unicast_primary_set(dsp->ds_mh,
 963             mp->b_rptr + dlp->dl_addr_offset);
 964         if (err != 0) {
 965                 switch (err) {
 966                 case EINVAL:
 967                         dl_err = DL_BADADDR;
 968                         err = 0;
 969                         break;
 970 
 971                 default:
 972                         dl_err = DL_SYSERR;
 973                         break;
 974                 }
 975                 dls_active_clear(dsp, B_FALSE);
 976                 goto failed2;
 977 
 978         }
 979 
 980         mac_perim_exit(mph);
 981 
 982         dlokack(q, mp, DL_SET_PHYS_ADDR_REQ);
 983         return;
 984 
 985 failed2:
 986         mac_perim_exit(mph);
 987 failed:
 988         dlerrorack(q, mp, DL_SET_PHYS_ADDR_REQ, dl_err, (t_uscalar_t)err);
 989 }
 990 
 991 /*
 992  * DL_UDQOS_REQ
 993  */
 994 static void
 995 proto_udqos_req(dld_str_t *dsp, mblk_t *mp)
 996 {
 997         dl_udqos_req_t *dlp = (dl_udqos_req_t *)mp->b_rptr;
 998         dl_qos_cl_sel1_t *selp;
 999         int             off, len;
1000         t_uscalar_t     dl_err;
1001         queue_t         *q = dsp->ds_wq;
1002 
1003         off = dlp->dl_qos_offset;
1004         len = dlp->dl_qos_length;
1005 
1006         if (MBLKL(mp) < sizeof (dl_udqos_req_t) || !MBLKIN(mp, off, len)) {
1007                 dl_err = DL_BADPRIM;
1008                 goto failed;
1009         }
1010 
1011         selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + off);
1012         if (selp->dl_qos_type != DL_QOS_CL_SEL1) {
1013                 dl_err = DL_BADQOSTYPE;
1014                 goto failed;
1015         }
1016 
1017         if (selp->dl_priority > (1 << VLAN_PRI_SIZE) - 1 ||
1018             selp->dl_priority < 0) {
1019                 dl_err = DL_BADQOSPARAM;
1020                 goto failed;
1021         }
1022 
1023         dsp->ds_pri = selp->dl_priority;
1024         dlokack(q, mp, DL_UDQOS_REQ);
1025         return;
1026 failed:
1027         dlerrorack(q, mp, DL_UDQOS_REQ, dl_err, 0);
1028 }
1029 
1030 static boolean_t
1031 check_mod_above(queue_t *q, const char *mod)
1032 {
1033         queue_t         *next_q;
1034         boolean_t       ret = B_TRUE;
1035 
1036         claimstr(q);
1037         next_q = q->q_next;
1038         if (strcmp(next_q->q_qinfo->qi_minfo->mi_idname, mod) != 0)
1039                 ret = B_FALSE;
1040         releasestr(q);
1041         return (ret);
1042 }
1043 
1044 /*
1045  * DL_CAPABILITY_REQ
1046  */
1047 static void
1048 proto_capability_req(dld_str_t *dsp, mblk_t *mp)
1049 {
1050         dl_capability_req_t *dlp = (dl_capability_req_t *)mp->b_rptr;
1051         dl_capability_sub_t *sp;
1052         size_t          size, len;
1053         offset_t        off, end;
1054         t_uscalar_t     dl_err;
1055         queue_t         *q = dsp->ds_wq;
1056 
1057         if (MBLKL(mp) < sizeof (dl_capability_req_t)) {
1058                 dl_err = DL_BADPRIM;
1059                 goto failed;
1060         }
1061 
1062         if (dsp->ds_dlstate == DL_UNATTACHED ||
1063             DL_ACK_PENDING(dsp->ds_dlstate)) {
1064                 dl_err = DL_OUTSTATE;
1065                 goto failed;
1066         }
1067 
1068         /*
1069          * This request is overloaded. If there are no requested capabilities
1070          * then we just want to acknowledge with all the capabilities we
1071          * support. Otherwise we enable the set of capabilities requested.
1072          */
1073         if (dlp->dl_sub_length == 0) {
1074                 proto_capability_advertise(dsp, mp);
1075                 return;
1076         }
1077 
1078         if (!MBLKIN(mp, dlp->dl_sub_offset, dlp->dl_sub_length)) {
1079                 dl_err = DL_BADPRIM;
1080                 goto failed;
1081         }
1082 
1083         dlp->dl_primitive = DL_CAPABILITY_ACK;
1084 
1085         off = dlp->dl_sub_offset;
1086         len = dlp->dl_sub_length;
1087 
1088         /*
1089          * Walk the list of capabilities to be enabled.
1090          */
1091         for (end = off + len; off < end; ) {
1092                 sp = (dl_capability_sub_t *)(mp->b_rptr + off);
1093                 size = sizeof (dl_capability_sub_t) + sp->dl_length;
1094 
1095                 if (off + size > end ||
1096                     !IS_P2ALIGNED(off, sizeof (uint32_t))) {
1097                         dl_err = DL_BADPRIM;
1098                         goto failed;
1099                 }
1100 
1101                 switch (sp->dl_cap) {
1102                 /*
1103                  * TCP/IP checksum offload to hardware.
1104                  */
1105                 case DL_CAPAB_HCKSUM: {
1106                         dl_capab_hcksum_t *hcksump;
1107                         dl_capab_hcksum_t hcksum;
1108 
1109                         hcksump = (dl_capab_hcksum_t *)&sp[1];
1110                         /*
1111                          * Copy for alignment.
1112                          */
1113                         bcopy(hcksump, &hcksum, sizeof (dl_capab_hcksum_t));
1114                         dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq);
1115                         bcopy(&hcksum, hcksump, sizeof (dl_capab_hcksum_t));
1116                         break;
1117                 }
1118 
1119                 case DL_CAPAB_DLD: {
1120                         dl_capab_dld_t  *dldp;
1121                         dl_capab_dld_t  dld;
1122 
1123                         dldp = (dl_capab_dld_t *)&sp[1];
1124                         /*
1125                          * Copy for alignment.
1126                          */
1127                         bcopy(dldp, &dld, sizeof (dl_capab_dld_t));
1128                         dlcapabsetqid(&(dld.dld_mid), dsp->ds_rq);
1129                         bcopy(&dld, dldp, sizeof (dl_capab_dld_t));
1130                         break;
1131                 }
1132                 default:
1133                         break;
1134                 }
1135                 off += size;
1136         }
1137         qreply(q, mp);
1138         return;
1139 failed:
1140         dlerrorack(q, mp, DL_CAPABILITY_REQ, dl_err, 0);
1141 }
1142 
1143 /*
1144  * DL_NOTIFY_REQ
1145  */
1146 static void
1147 proto_notify_req(dld_str_t *dsp, mblk_t *mp)
1148 {
1149         dl_notify_req_t *dlp = (dl_notify_req_t *)mp->b_rptr;
1150         t_uscalar_t     dl_err;
1151         queue_t         *q = dsp->ds_wq;
1152         uint_t          note =
1153             DL_NOTE_PROMISC_ON_PHYS |
1154             DL_NOTE_PROMISC_OFF_PHYS |
1155             DL_NOTE_PHYS_ADDR |
1156             DL_NOTE_LINK_UP |
1157             DL_NOTE_LINK_DOWN |
1158             DL_NOTE_CAPAB_RENEG |
1159             DL_NOTE_FASTPATH_FLUSH |
1160             DL_NOTE_SPEED |
1161             DL_NOTE_SDU_SIZE|
1162             DL_NOTE_SDU_SIZE2|
1163             DL_NOTE_ALLOWED_IPS;
1164 
1165         if (MBLKL(mp) < sizeof (dl_notify_req_t)) {
1166                 dl_err = DL_BADPRIM;
1167                 goto failed;
1168         }
1169 
1170         if (dsp->ds_dlstate == DL_UNATTACHED ||
1171             DL_ACK_PENDING(dsp->ds_dlstate)) {
1172                 dl_err = DL_OUTSTATE;
1173                 goto failed;
1174         }
1175 
1176         note &= ~(mac_no_notification(dsp->ds_mh));
1177 
1178         /*
1179          * Cache the notifications that are being enabled.
1180          */
1181         dsp->ds_notifications = dlp->dl_notifications & note;
1182         /*
1183          * The ACK carries all notifications regardless of which set is
1184          * being enabled.
1185          */
1186         dlnotifyack(q, mp, note);
1187 
1188         /*
1189          * Generate DL_NOTIFY_IND messages for each enabled notification.
1190          */
1191         if (dsp->ds_notifications != 0) {
1192                 dld_str_notify_ind(dsp);
1193         }
1194         return;
1195 failed:
1196         dlerrorack(q, mp, DL_NOTIFY_REQ, dl_err, 0);
1197 }
1198 
1199 /*
1200  * DL_UINTDATA_REQ
1201  */
1202 void
1203 proto_unitdata_req(dld_str_t *dsp, mblk_t *mp)
1204 {
1205         queue_t                 *q = dsp->ds_wq;
1206         dl_unitdata_req_t       *dlp = (dl_unitdata_req_t *)mp->b_rptr;
1207         off_t                   off;
1208         size_t                  len, size;
1209         const uint8_t           *addr;
1210         uint16_t                sap;
1211         uint_t                  addr_length;
1212         mblk_t                  *bp, *payload;
1213         uint32_t                start, stuff, end, value, flags;
1214         t_uscalar_t             dl_err;
1215         uint_t                  max_sdu;
1216 
1217         if (MBLKL(mp) < sizeof (dl_unitdata_req_t) || mp->b_cont == NULL) {
1218                 dlerrorack(q, mp, DL_UNITDATA_REQ, DL_BADPRIM, 0);
1219                 return;
1220         }
1221 
1222         mutex_enter(&dsp->ds_lock);
1223         if (dsp->ds_dlstate != DL_IDLE) {
1224                 mutex_exit(&dsp->ds_lock);
1225                 dlerrorack(q, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
1226                 return;
1227         }
1228         DLD_DATATHR_INC(dsp);
1229         mutex_exit(&dsp->ds_lock);
1230 
1231         addr_length = dsp->ds_mip->mi_addr_length;
1232 
1233         off = dlp->dl_dest_addr_offset;
1234         len = dlp->dl_dest_addr_length;
1235 
1236         if (!MBLKIN(mp, off, len) || !IS_P2ALIGNED(off, sizeof (uint16_t))) {
1237                 dl_err = DL_BADPRIM;
1238                 goto failed;
1239         }
1240 
1241         if (len != addr_length + sizeof (uint16_t)) {
1242                 dl_err = DL_BADADDR;
1243                 goto failed;
1244         }
1245 
1246         addr = mp->b_rptr + off;
1247         sap = *(uint16_t *)(mp->b_rptr + off + addr_length);
1248 
1249         /*
1250          * Check the length of the packet and the block types.
1251          */
1252         size = 0;
1253         payload = mp->b_cont;
1254         for (bp = payload; bp != NULL; bp = bp->b_cont) {
1255                 if (DB_TYPE(bp) != M_DATA)
1256                         goto baddata;
1257 
1258                 size += MBLKL(bp);
1259         }
1260 
1261         mac_sdu_get(dsp->ds_mh, NULL, &max_sdu);
1262         if (size > max_sdu)
1263                 goto baddata;
1264 
1265         /*
1266          * Build a packet header.
1267          */
1268         if ((bp = dls_header(dsp, addr, sap, dlp->dl_priority.dl_max,
1269             &payload)) == NULL) {
1270                 dl_err = DL_BADADDR;
1271                 goto failed;
1272         }
1273 
1274         /*
1275          * We no longer need the M_PROTO header, so free it.
1276          */
1277         freeb(mp);
1278 
1279         /*
1280          * Transfer the checksum offload information if it is present.
1281          */
1282         hcksum_retrieve(payload, NULL, NULL, &start, &stuff, &end, &value,
1283             &flags);
1284         (void) hcksum_assoc(bp, NULL, NULL, start, stuff, end, value, flags, 0);
1285 
1286         /*
1287          * Link the payload onto the new header.
1288          */
1289         ASSERT(bp->b_cont == NULL);
1290         bp->b_cont = payload;
1291 
1292         /*
1293          * No lock can be held across modules and putnext()'s,
1294          * which can happen here with the call from DLD_TX().
1295          */
1296         if (DLD_TX(dsp, bp, 0, 0) != NULL) {
1297                 /* flow-controlled */
1298                 DLD_SETQFULL(dsp);
1299         }
1300         DLD_DATATHR_DCR(dsp);
1301         return;
1302 
1303 failed:
1304         dlerrorack(q, mp, DL_UNITDATA_REQ, dl_err, 0);
1305         DLD_DATATHR_DCR(dsp);
1306         return;
1307 
1308 baddata:
1309         dluderrorind(q, mp, (void *)addr, len, DL_BADDATA, 0);
1310         DLD_DATATHR_DCR(dsp);
1311 }
1312 
1313 /*
1314  * DL_PASSIVE_REQ
1315  */
1316 static void
1317 proto_passive_req(dld_str_t *dsp, mblk_t *mp)
1318 {
1319         t_uscalar_t dl_err;
1320 
1321         /*
1322          * If we've already become active by issuing an active primitive,
1323          * then it's too late to try to become passive.
1324          */
1325         if (dsp->ds_passivestate == DLD_ACTIVE ||
1326             dsp->ds_passivestate == DLD_EXCLUSIVE) {
1327                 dl_err = DL_OUTSTATE;
1328                 goto failed;
1329         }
1330 
1331         if (MBLKL(mp) < sizeof (dl_passive_req_t)) {
1332                 dl_err = DL_BADPRIM;
1333                 goto failed;
1334         }
1335 
1336         dsp->ds_passivestate = DLD_PASSIVE;
1337         dlokack(dsp->ds_wq, mp, DL_PASSIVE_REQ);
1338         return;
1339 failed:
1340         dlerrorack(dsp->ds_wq, mp, DL_PASSIVE_REQ, dl_err, 0);
1341 }
1342 
1343 
1344 /*
1345  * Catch-all handler.
1346  */
1347 static void
1348 proto_req(dld_str_t *dsp, mblk_t *mp)
1349 {
1350         union DL_primitives     *dlp = (union DL_primitives *)mp->b_rptr;
1351 
1352         dlerrorack(dsp->ds_wq, mp, dlp->dl_primitive, DL_UNSUPPORTED, 0);
1353 }
1354 
1355 static int
1356 dld_capab_perim(dld_str_t *dsp, void *data, uint_t flags)
1357 {
1358         switch (flags) {
1359         case DLD_ENABLE:
1360                 mac_perim_enter_by_mh(dsp->ds_mh, (mac_perim_handle_t *)data);
1361                 return (0);
1362 
1363         case DLD_DISABLE:
1364                 mac_perim_exit((mac_perim_handle_t)data);
1365                 return (0);
1366 
1367         case DLD_QUERY:
1368                 return (mac_perim_held(dsp->ds_mh));
1369         }
1370         return (0);
1371 }
1372 
1373 static int
1374 dld_capab_direct(dld_str_t *dsp, void *data, uint_t flags)
1375 {
1376         dld_capab_direct_t      *direct = data;
1377 
1378         ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
1379 
1380         switch (flags) {
1381         case DLD_ENABLE:
1382                 dls_rx_set(dsp, (dls_rx_t)direct->di_rx_cf,
1383                     direct->di_rx_ch);
1384 
1385                 if (direct->di_flags & DI_DIRECT_RAW) {
1386                         direct->di_tx_df =
1387                             (uintptr_t)str_mdata_raw_fastpath_put;
1388                 } else {
1389                         direct->di_tx_df = (uintptr_t)str_mdata_fastpath_put;
1390                 }
1391                 direct->di_tx_dh = dsp;
1392                 direct->di_tx_cb_df = (uintptr_t)mac_client_tx_notify;
1393                 direct->di_tx_cb_dh = dsp->ds_mch;
1394                 direct->di_tx_fctl_df = (uintptr_t)mac_tx_is_flow_blocked;
1395                 direct->di_tx_fctl_dh = dsp->ds_mch;
1396 
1397                 dsp->ds_direct = B_TRUE;
1398 
1399                 return (0);
1400 
1401         case DLD_DISABLE:
1402                 dls_rx_set(dsp, (dsp->ds_mode == DLD_FASTPATH) ?
1403                     dld_str_rx_fastpath : dld_str_rx_unitdata, (void *)dsp);
1404                 dsp->ds_direct = B_FALSE;
1405 
1406                 return (0);
1407         }
1408         return (ENOTSUP);
1409 }
1410 
1411 /*
1412  * dld_capab_poll_enable()
1413  *
1414  * This function is misnamed. All polling  and fanouts are run out of the
1415  * lower mac (in case of VNIC and the only mac in case of NICs). The
1416  * availability of Rx ring and promiscous mode is all taken care between
1417  * the soft ring set (mac_srs), the Rx ring, and S/W classifier. Any
1418  * fanout necessary is done by the soft rings that are part of the
1419  * mac_srs (by default mac_srs sends the packets up via a TCP and
1420  * non TCP soft ring).
1421  *
1422  * The mac_srs (or its associated soft rings) always store the ill_rx_ring
1423  * (the cookie returned when they registered with IP during plumb) as their
1424  * 2nd argument which is passed up as mac_resource_handle_t. The upcall
1425  * function and 1st argument is what the caller registered when they
1426  * called mac_rx_classify_flow_add() to register the flow. For VNIC,
1427  * the function is vnic_rx and argument is vnic_t. For regular NIC
1428  * case, it mac_rx_default and mac_handle_t. As explained above, the
1429  * mac_srs (or its soft ring) will add the ill_rx_ring (mac_resource_handle_t)
1430  * from its stored 2nd argument.
1431  */
1432 static int
1433 dld_capab_poll_enable(dld_str_t *dsp, dld_capab_poll_t *poll)
1434 {
1435         if (dsp->ds_polling)
1436                 return (EINVAL);
1437 
1438         if ((dld_opt & DLD_OPT_NO_POLL) != 0 || dsp->ds_mode == DLD_RAW)
1439                 return (ENOTSUP);
1440 
1441         /*
1442          * Enable client polling if and only if DLS bypass is possible.
1443          * Special cases like VLANs need DLS processing in the Rx data path.
1444          * In such a case we can neither allow the client (IP) to directly
1445          * poll the softring (since DLS processing hasn't been done) nor can
1446          * we allow DLS bypass.
1447          */
1448         if (!mac_rx_bypass_set(dsp->ds_mch, dsp->ds_rx, dsp->ds_rx_arg))
1449                 return (ENOTSUP);
1450 
1451         /*
1452          * Register soft ring resources. This will come in handy later if
1453          * the user decides to modify CPU bindings to use more CPUs for the
1454          * device in which case we will switch to fanout using soft rings.
1455          */
1456         mac_resource_set_common(dsp->ds_mch,
1457             (mac_resource_add_t)poll->poll_ring_add_cf,
1458             (mac_resource_remove_t)poll->poll_ring_remove_cf,
1459             (mac_resource_quiesce_t)poll->poll_ring_quiesce_cf,
1460             (mac_resource_restart_t)poll->poll_ring_restart_cf,
1461             (mac_resource_bind_t)poll->poll_ring_bind_cf,
1462             poll->poll_ring_ch);
1463 
1464         mac_client_poll_enable(dsp->ds_mch);
1465 
1466         dsp->ds_polling = B_TRUE;
1467         return (0);
1468 }
1469 
1470 /* ARGSUSED */
1471 static int
1472 dld_capab_poll_disable(dld_str_t *dsp, dld_capab_poll_t *poll)
1473 {
1474         if (!dsp->ds_polling)
1475                 return (EINVAL);
1476 
1477         mac_client_poll_disable(dsp->ds_mch);
1478         mac_resource_set(dsp->ds_mch, NULL, NULL);
1479 
1480         dsp->ds_polling = B_FALSE;
1481         return (0);
1482 }
1483 
1484 static int
1485 dld_capab_poll(dld_str_t *dsp, void *data, uint_t flags)
1486 {
1487         dld_capab_poll_t        *poll = data;
1488 
1489         ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
1490 
1491         switch (flags) {
1492         case DLD_ENABLE:
1493                 return (dld_capab_poll_enable(dsp, poll));
1494         case DLD_DISABLE:
1495                 return (dld_capab_poll_disable(dsp, poll));
1496         }
1497         return (ENOTSUP);
1498 }
1499 
1500 static int
1501 dld_capab_lso(dld_str_t *dsp, void *data, uint_t flags)
1502 {
1503         dld_capab_lso_t         *lso = data;
1504 
1505         ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
1506 
1507         switch (flags) {
1508         case DLD_ENABLE: {
1509                 mac_capab_lso_t         mac_lso;
1510 
1511                 /*
1512                  * Check if LSO is supported on this MAC & enable LSO
1513                  * accordingly.
1514                  */
1515                 if (mac_capab_get(dsp->ds_mh, MAC_CAPAB_LSO, &mac_lso)) {
1516                         lso->lso_max = mac_lso.lso_basic_tcp_ipv4.lso_max;
1517                         lso->lso_flags = 0;
1518                         /* translate the flag for mac clients */
1519                         if ((mac_lso.lso_flags & LSO_TX_BASIC_TCP_IPV4) != 0)
1520                                 lso->lso_flags |= DLD_LSO_BASIC_TCP_IPV4;
1521                         dsp->ds_lso = B_TRUE;
1522                         dsp->ds_lso_max = lso->lso_max;
1523                 } else {
1524                         dsp->ds_lso = B_FALSE;
1525                         dsp->ds_lso_max = 0;
1526                         return (ENOTSUP);
1527                 }
1528                 return (0);
1529         }
1530         case DLD_DISABLE: {
1531                 dsp->ds_lso = B_FALSE;
1532                 dsp->ds_lso_max = 0;
1533                 return (0);
1534         }
1535         }
1536         return (ENOTSUP);
1537 }
1538 
1539 static int
1540 dld_capab(dld_str_t *dsp, uint_t type, void *data, uint_t flags)
1541 {
1542         int     err;
1543 
1544         /*
1545          * Don't enable direct callback capabilities unless the caller is
1546          * the IP client. When a module is inserted in a stream (_I_INSERT)
1547          * the stack initiates capability disable, but due to races, the
1548          * module insertion may complete before the capability disable
1549          * completes. So we limit the check to DLD_ENABLE case.
1550          */
1551         if ((flags == DLD_ENABLE && type != DLD_CAPAB_PERIM) &&
1552             ((dsp->ds_sap != ETHERTYPE_IP ||
1553             !check_mod_above(dsp->ds_rq, "ip")) &&
1554             !check_mod_above(dsp->ds_rq, "vnd"))) {
1555                 return (ENOTSUP);
1556         }
1557 
1558         switch (type) {
1559         case DLD_CAPAB_DIRECT:
1560                 err = dld_capab_direct(dsp, data, flags);
1561                 break;
1562 
1563         case DLD_CAPAB_POLL:
1564                 err =  dld_capab_poll(dsp, data, flags);
1565                 break;
1566 
1567         case DLD_CAPAB_PERIM:
1568                 err = dld_capab_perim(dsp, data, flags);
1569                 break;
1570 
1571         case DLD_CAPAB_LSO:
1572                 err = dld_capab_lso(dsp, data, flags);
1573                 break;
1574 
1575         default:
1576                 err = ENOTSUP;
1577                 break;
1578         }
1579 
1580         return (err);
1581 }
1582 
1583 /*
1584  * DL_CAPABILITY_ACK/DL_ERROR_ACK
1585  */
1586 static void
1587 proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
1588 {
1589         dl_capability_ack_t     *dlap;
1590         dl_capability_sub_t     *dlsp;
1591         size_t                  subsize;
1592         dl_capab_dld_t          dld;
1593         dl_capab_hcksum_t       hcksum;
1594         dl_capab_zerocopy_t     zcopy;
1595         dl_capab_vrrp_t         vrrp;
1596         mac_capab_vrrp_t        vrrp_capab;
1597         uint8_t                 *ptr;
1598         queue_t                 *q = dsp->ds_wq;
1599         mblk_t                  *mp1;
1600         boolean_t               hcksum_capable = B_FALSE;
1601         boolean_t               zcopy_capable = B_FALSE;
1602         boolean_t               dld_capable = B_FALSE;
1603         boolean_t               vrrp_capable = B_FALSE;
1604 
1605         /*
1606          * Initially assume no capabilities.
1607          */
1608         subsize = 0;
1609 
1610         /*
1611          * Check if checksum offload is supported on this MAC.
1612          */
1613         bzero(&hcksum, sizeof (dl_capab_hcksum_t));
1614         if (mac_capab_get(dsp->ds_mh, MAC_CAPAB_HCKSUM,
1615             &hcksum.hcksum_txflags)) {
1616                 if (hcksum.hcksum_txflags != 0) {
1617                         hcksum_capable = B_TRUE;
1618                         subsize += sizeof (dl_capability_sub_t) +
1619                             sizeof (dl_capab_hcksum_t);
1620                 }
1621         }
1622 
1623         /*
1624          * Check if zerocopy is supported on this interface.
1625          * If advertising DL_CAPAB_ZEROCOPY has not been explicitly disabled
1626          * then reserve space for that capability.
1627          */
1628         if (!mac_capab_get(dsp->ds_mh, MAC_CAPAB_NO_ZCOPY, NULL) &&
1629             !(dld_opt & DLD_OPT_NO_ZEROCOPY)) {
1630                 zcopy_capable = B_TRUE;
1631                 subsize += sizeof (dl_capability_sub_t) +
1632                     sizeof (dl_capab_zerocopy_t);
1633         }
1634 
1635         /*
1636          * Direct capability negotiation interface between IP/VND and DLD. Note
1637          * that for vnd we only allow the case where the media type is the
1638          * native media type so we know that there are no transformations that
1639          * would have to happen to the mac header that it receives.
1640          */
1641         if ((dsp->ds_sap == ETHERTYPE_IP &&
1642             check_mod_above(dsp->ds_rq, "ip")) ||
1643             (check_mod_above(dsp->ds_rq, "vnd") &&
1644             dsp->ds_mip->mi_media == dsp->ds_mip->mi_nativemedia)) {
1645                 dld_capable = B_TRUE;
1646                 subsize += sizeof (dl_capability_sub_t) +
1647                     sizeof (dl_capab_dld_t);
1648         }
1649 
1650         /*
1651          * Check if vrrp is supported on this interface. If so, reserve
1652          * space for that capability.
1653          */
1654         if (mac_capab_get(dsp->ds_mh, MAC_CAPAB_VRRP, &vrrp_capab)) {
1655                 vrrp_capable = B_TRUE;
1656                 subsize += sizeof (dl_capability_sub_t) +
1657                     sizeof (dl_capab_vrrp_t);
1658         }
1659 
1660         /*
1661          * If there are no capabilities to advertise or if we
1662          * can't allocate a response, send a DL_ERROR_ACK.
1663          */
1664         if ((mp1 = reallocb(mp,
1665             sizeof (dl_capability_ack_t) + subsize, 0)) == NULL) {
1666                 dlerrorack(q, mp, DL_CAPABILITY_REQ, DL_NOTSUPPORTED, 0);
1667                 return;
1668         }
1669 
1670         mp = mp1;
1671         DB_TYPE(mp) = M_PROTO;
1672         mp->b_wptr = mp->b_rptr + sizeof (dl_capability_ack_t) + subsize;
1673         bzero(mp->b_rptr, MBLKL(mp));
1674         dlap = (dl_capability_ack_t *)mp->b_rptr;
1675         dlap->dl_primitive = DL_CAPABILITY_ACK;
1676         dlap->dl_sub_offset = sizeof (dl_capability_ack_t);
1677         dlap->dl_sub_length = subsize;
1678         ptr = (uint8_t *)&dlap[1];
1679 
1680         /*
1681          * TCP/IP checksum offload.
1682          */
1683         if (hcksum_capable) {
1684                 dlsp = (dl_capability_sub_t *)ptr;
1685 
1686                 dlsp->dl_cap = DL_CAPAB_HCKSUM;
1687                 dlsp->dl_length = sizeof (dl_capab_hcksum_t);
1688                 ptr += sizeof (dl_capability_sub_t);
1689 
1690                 hcksum.hcksum_version = HCKSUM_VERSION_1;
1691                 dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq);
1692                 bcopy(&hcksum, ptr, sizeof (dl_capab_hcksum_t));
1693                 ptr += sizeof (dl_capab_hcksum_t);
1694         }
1695 
1696         /*
1697          * Zero copy
1698          */
1699         if (zcopy_capable) {
1700                 dlsp = (dl_capability_sub_t *)ptr;
1701 
1702                 dlsp->dl_cap = DL_CAPAB_ZEROCOPY;
1703                 dlsp->dl_length = sizeof (dl_capab_zerocopy_t);
1704                 ptr += sizeof (dl_capability_sub_t);
1705 
1706                 bzero(&zcopy, sizeof (dl_capab_zerocopy_t));
1707                 zcopy.zerocopy_version = ZEROCOPY_VERSION_1;
1708                 zcopy.zerocopy_flags = DL_CAPAB_VMSAFE_MEM;
1709 
1710                 dlcapabsetqid(&(zcopy.zerocopy_mid), dsp->ds_rq);
1711                 bcopy(&zcopy, ptr, sizeof (dl_capab_zerocopy_t));
1712                 ptr += sizeof (dl_capab_zerocopy_t);
1713         }
1714 
1715         /*
1716          * VRRP capability negotiation
1717          */
1718         if (vrrp_capable) {
1719                 dlsp = (dl_capability_sub_t *)ptr;
1720                 dlsp->dl_cap = DL_CAPAB_VRRP;
1721                 dlsp->dl_length = sizeof (dl_capab_vrrp_t);
1722                 ptr += sizeof (dl_capability_sub_t);
1723 
1724                 bzero(&vrrp, sizeof (dl_capab_vrrp_t));
1725                 vrrp.vrrp_af = vrrp_capab.mcv_af;
1726                 bcopy(&vrrp, ptr, sizeof (dl_capab_vrrp_t));
1727                 ptr += sizeof (dl_capab_vrrp_t);
1728         }
1729 
1730         /*
1731          * Direct capability negotiation interface between IP and DLD.
1732          * Refer to dld.h for details.
1733          */
1734         if (dld_capable) {
1735                 dlsp = (dl_capability_sub_t *)ptr;
1736                 dlsp->dl_cap = DL_CAPAB_DLD;
1737                 dlsp->dl_length = sizeof (dl_capab_dld_t);
1738                 ptr += sizeof (dl_capability_sub_t);
1739 
1740                 bzero(&dld, sizeof (dl_capab_dld_t));
1741                 dld.dld_version = DLD_CURRENT_VERSION;
1742                 dld.dld_capab = (uintptr_t)dld_capab;
1743                 dld.dld_capab_handle = (uintptr_t)dsp;
1744 
1745                 dlcapabsetqid(&(dld.dld_mid), dsp->ds_rq);
1746                 bcopy(&dld, ptr, sizeof (dl_capab_dld_t));
1747                 ptr += sizeof (dl_capab_dld_t);
1748         }
1749 
1750         ASSERT(ptr == mp->b_rptr + sizeof (dl_capability_ack_t) + subsize);
1751         qreply(q, mp);
1752 }
1753 
1754 /*
1755  * Disable any enabled capabilities.
1756  */
1757 void
1758 dld_capabilities_disable(dld_str_t *dsp)
1759 {
1760         if (dsp->ds_polling)
1761                 (void) dld_capab_poll_disable(dsp, NULL);
1762 }
1763 
1764 static void
1765 proto_exclusive_req(dld_str_t *dsp, mblk_t *mp)
1766 {
1767         int ret = 0;
1768         t_uscalar_t dl_err;
1769         mac_perim_handle_t mph;
1770 
1771         if (dsp->ds_passivestate != DLD_UNINITIALIZED) {
1772                 dl_err = DL_OUTSTATE;
1773                 goto failed;
1774         }
1775 
1776         if (MBLKL(mp) < DL_EXCLUSIVE_REQ_SIZE) {
1777                 dl_err = DL_BADPRIM;
1778                 goto failed;
1779         }
1780 
1781         mac_perim_enter_by_mh(dsp->ds_mh, &mph);
1782         ret = dls_exclusive_set(dsp, B_TRUE);
1783         mac_perim_exit(mph);
1784 
1785         if (ret != 0) {
1786                 dl_err = DL_SYSERR;
1787                 goto failed;
1788         }
1789 
1790         dsp->ds_passivestate = DLD_EXCLUSIVE;
1791         dlokack(dsp->ds_wq, mp, DL_EXCLUSIVE_REQ);
1792         return;
1793 failed:
1794         dlerrorack(dsp->ds_wq, mp, DL_EXCLUSIVE_REQ, dl_err, (t_uscalar_t)ret);
1795 }