17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5f12af565Snd99603 * Common Development and Distribution License (the "License").
6f12af565Snd99603 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22d62bc4baSyz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate * IEEE 802.3ad Link Aggregation - Receive
287c478bd9Sstevel@tonic-gate *
297c478bd9Sstevel@tonic-gate * Implements the collector function.
307c478bd9Sstevel@tonic-gate * Manages the RX resources exposed by a link aggregation group.
317c478bd9Sstevel@tonic-gate */
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
357c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
367c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
377c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
387c478bd9Sstevel@tonic-gate #include <sys/byteorder.h>
397c478bd9Sstevel@tonic-gate #include <sys/aggr.h>
407c478bd9Sstevel@tonic-gate #include <sys/aggr_impl.h>
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate static void
aggr_mac_rx(mac_handle_t lg_mh,mac_resource_handle_t mrh,mblk_t * mp)43*da14cebeSEric Cheng aggr_mac_rx(mac_handle_t lg_mh, mac_resource_handle_t mrh, mblk_t *mp)
44*da14cebeSEric Cheng {
45*da14cebeSEric Cheng if (mrh == NULL) {
46*da14cebeSEric Cheng mac_rx(lg_mh, mrh, mp);
47*da14cebeSEric Cheng } else {
48*da14cebeSEric Cheng aggr_pseudo_rx_ring_t *ring = (aggr_pseudo_rx_ring_t *)mrh;
49*da14cebeSEric Cheng mac_rx_ring(lg_mh, ring->arr_rh, mp, ring->arr_gen);
50*da14cebeSEric Cheng }
51*da14cebeSEric Cheng }
52*da14cebeSEric Cheng
53*da14cebeSEric Cheng void
aggr_recv_lacp(aggr_port_t * port,mac_resource_handle_t mrh,mblk_t * mp)54*da14cebeSEric Cheng aggr_recv_lacp(aggr_port_t *port, mac_resource_handle_t mrh, mblk_t *mp)
557c478bd9Sstevel@tonic-gate {
567c478bd9Sstevel@tonic-gate aggr_grp_t *grp = port->lp_grp;
577c478bd9Sstevel@tonic-gate
58d62bc4baSyz147064 /* in promiscuous mode, send copy of packet up */
597c478bd9Sstevel@tonic-gate if (grp->lg_promisc) {
607c478bd9Sstevel@tonic-gate mblk_t *nmp = copymsg(mp);
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate if (nmp != NULL)
63*da14cebeSEric Cheng aggr_mac_rx(grp->lg_mh, mrh, nmp);
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate
66*da14cebeSEric Cheng aggr_lacp_rx_enqueue(port, mp);
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate * Callback function invoked by MAC service module when packets are
717c478bd9Sstevel@tonic-gate * made available by a MAC port.
727c478bd9Sstevel@tonic-gate */
73*da14cebeSEric Cheng /* ARGSUSED */
747c478bd9Sstevel@tonic-gate void
aggr_recv_cb(void * arg,mac_resource_handle_t mrh,mblk_t * mp,boolean_t loopback)75*da14cebeSEric Cheng aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
76*da14cebeSEric Cheng boolean_t loopback)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate aggr_port_t *port = (aggr_port_t *)arg;
797c478bd9Sstevel@tonic-gate aggr_grp_t *grp = port->lp_grp;
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate if (grp->lg_lacp_mode == AGGR_LACP_OFF) {
82*da14cebeSEric Cheng aggr_mac_rx(grp->lg_mh, mrh, mp);
837c478bd9Sstevel@tonic-gate } else {
847c478bd9Sstevel@tonic-gate mblk_t *cmp, *last, *head;
857c478bd9Sstevel@tonic-gate struct ether_header *ehp;
867c478bd9Sstevel@tonic-gate uint16_t sap;
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate /* filter out slow protocol packets (LACP & Marker) */
897c478bd9Sstevel@tonic-gate last = NULL;
907c478bd9Sstevel@tonic-gate head = cmp = mp;
917c478bd9Sstevel@tonic-gate while (cmp != NULL) {
927c478bd9Sstevel@tonic-gate if (MBLKL(cmp) < sizeof (struct ether_header)) {
937c478bd9Sstevel@tonic-gate /* packet too short */
947c478bd9Sstevel@tonic-gate if (head == cmp) {
957c478bd9Sstevel@tonic-gate /* no packets accumulated */
967c478bd9Sstevel@tonic-gate head = cmp->b_next;
977c478bd9Sstevel@tonic-gate cmp->b_next = NULL;
987c478bd9Sstevel@tonic-gate freemsg(cmp);
997c478bd9Sstevel@tonic-gate cmp = head;
1007c478bd9Sstevel@tonic-gate } else {
1017c478bd9Sstevel@tonic-gate /* send up accumulated packets */
1027c478bd9Sstevel@tonic-gate last->b_next = NULL;
103*da14cebeSEric Cheng if (port->lp_collector_enabled) {
104*da14cebeSEric Cheng aggr_mac_rx(grp->lg_mh, mrh,
105*da14cebeSEric Cheng head);
106*da14cebeSEric Cheng } else {
107f12af565Snd99603 freemsgchain(head);
108*da14cebeSEric Cheng }
1097c478bd9Sstevel@tonic-gate head = cmp->b_next;
1107c478bd9Sstevel@tonic-gate cmp->b_next = NULL;
1117c478bd9Sstevel@tonic-gate freemsg(cmp);
1127c478bd9Sstevel@tonic-gate cmp = head;
1137c478bd9Sstevel@tonic-gate last = NULL;
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate continue;
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate ehp = (struct ether_header *)cmp->b_rptr;
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate sap = ntohs(ehp->ether_type);
1207c478bd9Sstevel@tonic-gate if (sap == ETHERTYPE_SLOW) {
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate * LACP or Marker packet. Send up pending
1237c478bd9Sstevel@tonic-gate * chain, and send LACP/Marker packet
1247c478bd9Sstevel@tonic-gate * to LACP subsystem.
1257c478bd9Sstevel@tonic-gate */
1267c478bd9Sstevel@tonic-gate if (head == cmp) {
1277c478bd9Sstevel@tonic-gate /* first packet of chain */
1287c478bd9Sstevel@tonic-gate ASSERT(last == NULL);
1297c478bd9Sstevel@tonic-gate head = cmp->b_next;
1307c478bd9Sstevel@tonic-gate cmp->b_next = NULL;
131*da14cebeSEric Cheng aggr_recv_lacp(port, mrh, cmp);
1327c478bd9Sstevel@tonic-gate cmp = head;
1337c478bd9Sstevel@tonic-gate } else {
1347c478bd9Sstevel@tonic-gate /* previously accumulated packets */
1357c478bd9Sstevel@tonic-gate ASSERT(last != NULL);
1367c478bd9Sstevel@tonic-gate /* send up non-LACP packets */
1377c478bd9Sstevel@tonic-gate last->b_next = NULL;
138*da14cebeSEric Cheng if (port->lp_collector_enabled) {
139*da14cebeSEric Cheng aggr_mac_rx(grp->lg_mh, mrh,
140*da14cebeSEric Cheng head);
141*da14cebeSEric Cheng } else {
142f12af565Snd99603 freemsgchain(head);
143*da14cebeSEric Cheng }
1447c478bd9Sstevel@tonic-gate /* unlink and pass up LACP packets */
1457c478bd9Sstevel@tonic-gate head = cmp->b_next;
1467c478bd9Sstevel@tonic-gate cmp->b_next = NULL;
147*da14cebeSEric Cheng aggr_recv_lacp(port, mrh, cmp);
1487c478bd9Sstevel@tonic-gate cmp = head;
1497c478bd9Sstevel@tonic-gate last = NULL;
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate } else {
1527c478bd9Sstevel@tonic-gate last = cmp;
1537c478bd9Sstevel@tonic-gate cmp = cmp->b_next;
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate if (head != NULL) {
1577c478bd9Sstevel@tonic-gate if (port->lp_collector_enabled)
158*da14cebeSEric Cheng aggr_mac_rx(grp->lg_mh, mrh, head);
1597c478bd9Sstevel@tonic-gate else
160f12af565Snd99603 freemsgchain(head);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate }
164