Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / aggr / aggr_recv.c
blob2bdb7872e33a0728af75e74a12e240ae2458274a
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * IEEE 802.3ad Link Aggregation - Receive
29 * Implements the collector function.
30 * Manages the RX resources exposed by a link aggregation group.
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>
42 static void
43 aggr_mac_rx(mac_handle_t lg_mh, mac_resource_handle_t mrh, mblk_t *mp)
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);
53 void
54 aggr_recv_lacp(aggr_port_t *port, mac_resource_handle_t mrh, mblk_t *mp)
56 aggr_grp_t *grp = port->lp_grp;
58 /* in promiscuous mode, send copy of packet up */
59 if (grp->lg_promisc) {
60 mblk_t *nmp = copymsg(mp);
62 if (nmp != NULL)
63 aggr_mac_rx(grp->lg_mh, mrh, nmp);
66 aggr_lacp_rx_enqueue(port, mp);
70 * Callback function invoked by MAC service module when packets are
71 * made available by a MAC port.
73 /* ARGSUSED */
74 void
75 aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
76 boolean_t loopback)
78 aggr_port_t *port = (aggr_port_t *)arg;
79 aggr_grp_t *grp = port->lp_grp;
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;
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);
109 head = cmp->b_next;
110 cmp->b_next = NULL;
111 freemsg(cmp);
112 cmp = head;
113 last = NULL;
115 continue;
117 ehp = (struct ether_header *)cmp->b_rptr;
119 sap = ntohs(ehp->ether_type);
120 if (sap == ETHERTYPE_SLOW) {
122 * LACP or Marker packet. Send up pending
123 * chain, and send LACP/Marker packet
124 * to LACP subsystem.
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);
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;
151 } else {
152 last = cmp;
153 cmp = cmp->b_next;
156 if (head != NULL) {
157 if (port->lp_collector_enabled)
158 aggr_mac_rx(grp->lg_mh, mrh, head);
159 else
160 freemsgchain(head);