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 /* ARGSUSED */ 74 void 75 aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp, 76 boolean_t loopback) 77 { 78 aggr_port_t *port = (aggr_port_t *)arg; 79 aggr_grp_t *grp = port->lp_grp; 80 81 if (grp->lg_lacp_mode == AGGR_LACP_OFF) { 82 aggr_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 aggr_mac_rx(grp->lg_mh, mrh, 105 head); 106 } else { 107 freemsgchain(head); 108 } 109 head = cmp->b_next; 110 cmp->b_next = NULL; 111 freemsg(cmp); 112 cmp = head; 113 last = NULL; 114 } 115 continue; 116 } 117 ehp = (struct ether_header *)cmp->b_rptr; 118 119 sap = ntohs(ehp->ether_type); 120 if (sap == ETHERTYPE_SLOW) { 121 /* 122 * LACP or Marker packet. Send up pending 123 * chain, and send LACP/Marker packet 124 * to LACP subsystem. 125 */ 126 if (head == cmp) { 127 /* first packet of chain */ 128 ASSERT(last == NULL); 129 head = cmp->b_next; 130 cmp->b_next = NULL; 131 aggr_recv_lacp(port, mrh, cmp); 132 cmp = head; 133 } else { 134 /* previously accumulated packets */ 135 ASSERT(last != NULL); 136 /* send up non-LACP packets */ 137 last->b_next = NULL; 138 if (port->lp_collector_enabled) { 139 aggr_mac_rx(grp->lg_mh, mrh, 140 head); 141 } else { 142 freemsgchain(head); 143 } 144 /* unlink and pass up LACP packets */ 145 head = cmp->b_next; 146 cmp->b_next = NULL; 147 aggr_recv_lacp(port, mrh, cmp); 148 cmp = head; 149 last = NULL; 150 } 151 } else { 152 last = cmp; 153 cmp = cmp->b_next; 154 } 155 } 156 if (head != NULL) { 157 if (port->lp_collector_enabled) 158 aggr_mac_rx(grp->lg_mh, mrh, head); 159 else 160 freemsgchain(head); 161 } 162 } 163 }