Crossbow - transition to Mercurial
6668161 expose receive rings through aggregations
6741067 aggr locking needs to work with mac perimeter design
6734073 deadlock in aggr if aggregation failed to be created for some reason
6742825 system panicked due to recursive locking in aggr
6746501 deadbeef panic in mac_client_close()
6742712 potential message double free in the aggr driver
6754299 a potential race between aggr_m_tx() and aggr_port_delete()

   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 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 /*
  29  * IEEE 802.3ad Link Aggregation - Receive
  30  *
  31  * Implements the collector function.
  32  * Manages the RX resources exposed by a link aggregation group.
  33  */
  34 
  35 #include <sys/sysmacros.h>
  36 #include <sys/ddi.h>
  37 #include <sys/sunddi.h>
  38 #include <sys/strsun.h>
  39 #include <sys/strsubr.h>
  40 #include <sys/byteorder.h>
  41 #include <sys/aggr.h>
  42 #include <sys/aggr_impl.h>
  43 
  44 static void
  45 aggr_recv_lacp(aggr_port_t *port, mblk_t *mp)
  46 {











  47         aggr_grp_t *grp = port->lp_grp;
  48 
  49         /* in promiscuous mode, send copy of packet up */
  50         if (grp->lg_promisc) {
  51                 mblk_t *nmp = copymsg(mp);
  52 
  53                 if (nmp != NULL)
  54                         mac_rx(grp->lg_mh, NULL, nmp);
  55         }
  56 
  57         aggr_lacp_rx(port, mp);
  58 }
  59 
  60 /*
  61  * Callback function invoked by MAC service module when packets are
  62  * made available by a MAC port.

















  63  */

  64 void
  65 aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp)

  66 {
  67         aggr_port_t *port = (aggr_port_t *)arg;
  68         aggr_grp_t *grp = port->lp_grp;
  69 
  70         /*
  71          * If this message is looped back from the legacy devices, drop
  72          * it as the Nemo framework will be responsible for looping it
  73          * back by the mac_txloop() function.
  74          */
  75         if (mp->b_flag & MSGNOLOOP) {
  76                 ASSERT(mp->b_next == NULL);
  77                 freemsg(mp);
  78                 return;
  79         }
  80 
  81         if (grp->lg_lacp_mode == AGGR_LACP_OFF) {
  82                 mac_rx(grp->lg_mh, mrh, mp);
  83         } else {
  84                 mblk_t *cmp, *last, *head;
  85                 struct ether_header *ehp;
  86                 uint16_t sap;
  87 
  88                 /* filter out slow protocol packets (LACP & Marker) */
  89                 last = NULL;
  90                 head = cmp = mp;
  91                 while (cmp != NULL) {
  92                         if (MBLKL(cmp) < sizeof (struct ether_header)) {
  93                                 /* packet too short */
  94                                 if (head == cmp) {
  95                                         /* no packets accumulated */
  96                                         head = cmp->b_next;
  97                                         cmp->b_next = NULL;
  98                                         freemsg(cmp);
  99                                         cmp = head;
 100                                 } else {
 101                                         /* send up accumulated packets */
 102                                         last->b_next = NULL;
 103                                         if (port->lp_collector_enabled)
 104                                                 mac_rx(grp->lg_mh, mrh, head);
 105                                         else

 106                                                 freemsgchain(head);

 107                                         head = cmp->b_next;
 108                                         cmp->b_next = NULL;
 109                                         freemsg(cmp);
 110                                         cmp = head;
 111                                         last = NULL;
 112                                 }
 113                                 continue;
 114                         }
 115                         ehp = (struct ether_header *)cmp->b_rptr;
 116 
 117                         sap = ntohs(ehp->ether_type);
 118                         if (sap == ETHERTYPE_SLOW) {
 119                                 /*
 120                                  * LACP or Marker packet. Send up pending
 121                                  * chain, and send LACP/Marker packet
 122                                  * to LACP subsystem.
 123                                  */
 124                                 if (head == cmp) {
 125                                         /* first packet of chain */
 126                                         ASSERT(last == NULL);
 127                                         head = cmp->b_next;
 128                                         cmp->b_next = NULL;
 129                                         aggr_recv_lacp(port, cmp);
 130                                         cmp = head;
 131                                 } else {
 132                                         /* previously accumulated packets */
 133                                         ASSERT(last != NULL);
 134                                         /* send up non-LACP packets */
 135                                         last->b_next = NULL;
 136                                         if (port->lp_collector_enabled)
 137                                                 mac_rx(grp->lg_mh, mrh, head);
 138                                         else

 139                                                 freemsgchain(head);

 140                                         /* unlink and pass up LACP packets */
 141                                         head = cmp->b_next;
 142                                         cmp->b_next = NULL;
 143                                         aggr_recv_lacp(port, cmp);
 144                                         cmp = head;
 145                                         last = NULL;
 146                                 }
 147                         } else {
 148                                 last = cmp;
 149                                 cmp = cmp->b_next;
 150                         }
 151                 }
 152                 if (head != NULL) {
 153                         if (port->lp_collector_enabled)
 154                                 mac_rx(grp->lg_mh, mrh, head);
 155                         else
 156                                 freemsgchain(head);
 157                 }
 158         }
 159 }
--- EOF ---