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 /*
  27  * IEEE 802.3ad Link Aggregation - Receive
  28  *
  29  * Implements the collector function.
  30  * Manages the RX resources exposed by a link aggregation group.
  31  */
  32 
  33 #include <sys/sysmacros.h>
  34 #include <sys/ddi.h>
  35 #include <sys/sunddi.h>
  36 #include <sys/strsun.h>
  37 #include <sys/strsubr.h>
  38 #include <sys/byteorder.h>
  39 #include <sys/aggr.h>
  40 #include <sys/aggr_impl.h>
  41 
  42 static void
  43 aggr_mac_rx(mac_handle_t lg_mh, mac_resource_handle_t mrh, mblk_t *mp)
  44 {
  45         if (mrh == NULL) {
  46                 mac_rx(lg_mh, mrh, mp);
  47         } else {
  48                 aggr_pseudo_rx_ring_t   *ring = (aggr_pseudo_rx_ring_t *)mrh;
  49                 mac_rx_ring(lg_mh, ring->arr_rh, mp, ring->arr_gen);
  50         }
  51 }
  52 
  53 void
  54 aggr_recv_lacp(aggr_port_t *port, mac_resource_handle_t mrh, mblk_t *mp)
  55 {
  56         aggr_grp_t *grp = port->lp_grp;
  57 
  58         /* in promiscuous mode, send copy of packet up */
  59         if (grp->lg_promisc) {
  60                 mblk_t *nmp = copymsg(mp);
  61 
  62                 if (nmp != NULL)
  63                         aggr_mac_rx(grp->lg_mh, mrh, nmp);
  64         }
  65 
  66         aggr_lacp_rx_enqueue(port, mp);
  67 }
  68 
  69 /*
  70  * Callback function invoked by MAC service module when packets are
  71  * made available by a MAC port.
  72  *
  73  * XXX-kb. All calls to mac_rx() take NULL instead of the 'mrh' coming
  74  * from the member drivers.
  75  * Passing NULL will cause a first SW classification that will revover
  76  * the aggr's primary MAC address flow, and deliver the packet to that
  77  * flow's SW SRS.
  78  * The 'mrh' here maps to a mac_ring_t set up by MAC at the lower level.
  79  * It is likely to be flagged as pollable with HW_CLASSIFIER ON since
  80  * at that level, MAC saw a single client claiming that ring, therefore
  81  * it assigned it to an SRS that will toggle the interrupts and polls
  82  * packets from it at its own whim.
  83  * Passing the same 'mrh' along to the MAC at the level of aggr will
  84  * run the packets by the same SRS again. Needless to say it will also
  85  * cause skipping the classification to multiple flows (for multiple
  86  * MAC clients) therefore occasionally losign packets destined to
  87  * VNICs over the aggr.
  88  *
  89  */
  90 /* ARGSUSED */
  91 void
  92 aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
  93     boolean_t loopback)
  94 {
  95         aggr_port_t *port = (aggr_port_t *)arg;
  96         aggr_grp_t *grp = port->lp_grp;
  97 











  98         if (grp->lg_lacp_mode == AGGR_LACP_OFF) {
  99                 aggr_mac_rx(grp->lg_mh, mrh, mp);
 100         } else {
 101                 mblk_t *cmp, *last, *head;
 102                 struct ether_header *ehp;
 103                 uint16_t sap;
 104 
 105                 /* filter out slow protocol packets (LACP & Marker) */
 106                 last = NULL;
 107                 head = cmp = mp;
 108                 while (cmp != NULL) {
 109                         if (MBLKL(cmp) < sizeof (struct ether_header)) {
 110                                 /* packet too short */
 111                                 if (head == cmp) {
 112                                         /* no packets accumulated */
 113                                         head = cmp->b_next;
 114                                         cmp->b_next = NULL;
 115                                         freemsg(cmp);
 116                                         cmp = head;
 117                                 } else {
 118                                         /* send up accumulated packets */
 119                                         last->b_next = NULL;
 120                                         if (port->lp_collector_enabled) {
 121                                                 aggr_mac_rx(grp->lg_mh, mrh,
 122                                                     head);
 123                                         } else {
 124                                                 freemsgchain(head);
 125                                         }
 126                                         head = cmp->b_next;
 127                                         cmp->b_next = NULL;
 128                                         freemsg(cmp);
 129                                         cmp = head;
 130                                         last = NULL;
 131                                 }
 132                                 continue;
 133                         }
 134                         ehp = (struct ether_header *)cmp->b_rptr;
 135 
 136                         sap = ntohs(ehp->ether_type);
 137                         if (sap == ETHERTYPE_SLOW) {
 138                                 /*
 139                                  * LACP or Marker packet. Send up pending
 140                                  * chain, and send LACP/Marker packet
 141                                  * to LACP subsystem.
 142                                  */
 143                                 if (head == cmp) {
 144                                         /* first packet of chain */
 145                                         ASSERT(last == NULL);
 146                                         head = cmp->b_next;
 147                                         cmp->b_next = NULL;
 148                                         aggr_recv_lacp(port, mrh, cmp);
 149                                         cmp = head;
 150                                 } else {
 151                                         /* previously accumulated packets */
 152                                         ASSERT(last != NULL);
 153                                         /* send up non-LACP packets */
 154                                         last->b_next = NULL;
 155                                         if (port->lp_collector_enabled) {
 156                                                 aggr_mac_rx(grp->lg_mh, mrh,
 157                                                     head);
 158                                         } else {
 159                                                 freemsgchain(head);
 160                                         }
 161                                         /* unlink and pass up LACP packets */
 162                                         head = cmp->b_next;
 163                                         cmp->b_next = NULL;
 164                                         aggr_recv_lacp(port, mrh, cmp);
 165                                         cmp = head;
 166                                         last = NULL;
 167                                 }
 168                         } else {
 169                                 last = cmp;
 170                                 cmp = cmp->b_next;
 171                         }
 172                 }
 173                 if (head != NULL) {
 174                         if (port->lp_collector_enabled)
 175                                 aggr_mac_rx(grp->lg_mh, mrh, head);
 176                         else
 177                                 freemsgchain(head);
 178                 }
 179         }
 180 }
--- EOF ---