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 ---